home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat España 15
/
macformat_15.iso
/
Shareware Internet
/
Ciencia
/
CFG 2.3 (Shareware)
/
µCinema Converter
/
PICS to QuickTime.c
< prev
next >
Wrap
Text File
|
1994-04-10
|
11KB
|
409 lines
/********************************************************************
µCinema Converter 1.0
module: PICS to QuickTime.c
February 1994 - April 1994
by John A. Schlack
*********************************************************************************/
#include <Movies.h>
#include <Script.h>
#include "constants.h"
#include "PICS to QuickTime.h"
#include "preferences.h"
#include "pstring.h"
#include "µCinema.h"
/* --------------------------------------------------------------------------------- */
#define BASE_PICT_INDEX 128
/* --------------------------------------------------------------------------------- */
typedef struct pics_info
{
short bwColor; // 0 = BW, 1 = color
short depth; // bits per pixel
short speed; // frames per second ???
short version; // set to 0
OSType creator;
long maxFrame; // maximum frame size
} pics_info;
/* --------------------------------------------------------------------------------- */
static pics_info rPICSInfo;
static short basePictIndex;
/* --------------------------------------------------------------------------------- */
static void picsToMovie( FSSpec * picsFile, FSSpec * movieFile );
static void CreateMyVideoTrack( Movie theMovie, FSSpec * spec );
static void AddVideoSamples( Media theMedia, Rect * trackFrame, long max,
unsigned char * picsFileName );
static void DrawMyFrame( Rect * trackFrame, short id );
static Boolean inputFileValid( FSSpec * picsFile, Boolean interactive );
static void buildName( unsigned char * newBaseName, unsigned char * variant );
/* --------------------------------------------------------------------------------- */
void picsToMovieBatch( FSSpec * picsFile )
{
FSSpec movieFile;
Str63 tempName;
long attempts;
short fileRefNo;
if (!inputFileValid( picsFile, false ))
return;
/* build file name, if file with duplicate name present, try a new name */
movieFile = *picsFile;
pstrcpy( tempName, movieFile.name );
buildName( tempName, movieFile.name );
for (attempts=0L; attempts<1000L; attempts++)
{
if (FSpOpenRF( &movieFile, fsRdPerm, &fileRefNo ) != noErr)
break;
FSClose( fileRefNo );
buildName( nil, movieFile.name );
}
/* abort if failed to find new name after great number of attempts */
if (attempts >= 1000L)
{
errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
return;
}
/* convert the file */
picsToMovie( picsFile, &movieFile );
}
/* --------------------------------------------------------------------------------- */
void picsToMovieInteractive( void )
{
Str63 tempName;
SFTypeList typelist;
StandardFileReply getreply, putreply;
typelist[0] = 'PICS';
StandardGetFile(nil, 1, typelist, &getreply);
if (!getreply.sfGood)
return;
if (!inputFileValid( &getreply.sfFile, true ))
return;
buildName( getreply.sfFile.name, tempName );
StandardPutFile("\pSave movie as:", tempName, &putreply);
if (!putreply.sfGood)
return;
picsToMovie( &getreply.sfFile, &putreply.sfFile );
}
/* --------------------------------------------------------------------------------- */
static void picsToMovie( FSSpec * picsFile, FSSpec * movieFile )
{
Movie theMovie = nil;
OSErr err = noErr;
short saveref, resRefNum = 0, resId = 0;
saveref = CurResFile();
err = EnterMovies();
err = CreateMovieFile( movieFile, 'SPLY', smCurrentScript, createMovieFileDeleteCurFile,
&resRefNum, &theMovie );
CreateMyVideoTrack( theMovie, picsFile );
err = AddMovieResource( theMovie, resRefNum, &resId, movieFile->name );
if (resRefNum)
CloseMovieFile( resRefNum );
UseResFile(saveref);
ExitMovies();
}
/* --------------------------------------------------------------------------------- */
static void CreateMyVideoTrack( Movie theMovie, FSSpec * spec )
{
Str255 dummyName;
ResType dummyType;
Track theTrack;
Media theMedia;
OSErr err = noErr;
Rect trackFrame = { 0, 0, 160, 120 };
Handle myres;
short resfile, max;
resfile = FSpOpenResFile( spec, fsRdPerm );
if (resfile == -1)
{
errorHandlerParameter( ERR_INPUT_FILE, spec->name );
return;
}
UseResFile( resfile );
max = Count1Resources( 'PICT' );
if (max <= 0)
{
errorHandlerParameter( ERR_PICS_DATA, spec->name );
return;
}
/*
Attempt to get first PICT data item. The default is index 128. If it is
not there, get first PICT item. Abort if item index is less than 128.
*/
basePictIndex = BASE_PICT_INDEX;
myres = Get1Resource( 'PICT', basePictIndex );
if (myres == NULL)
{
myres = Get1IndResource( 'PICT', 1 );
if (myres != NULL)
{
GetResInfo( myres, &basePictIndex, &dummyType, dummyName );
if (basePictIndex < BASE_PICT_INDEX)
{
ReleaseResource( myres );
myres = nil;
}
}
}
if (myres == nil)
{
errorHandlerParameter( ERR_PICS_DATA, spec->name );
return;
}
LoadResource( myres );
trackFrame = (**((PicHandle) myres)).picFrame;
ReleaseResource( myres );
theTrack = NewMovieTrack( theMovie, FixRatio( trackFrame.right, 1 ),
FixRatio( trackFrame.bottom, 1 ), kNoVolume );
err = GetMoviesError();
theMedia = NewTrackMedia( theTrack, VideoMediaType, rPICSInfo.speed, NULL, 0 );
err = GetMoviesError();
err = BeginMediaEdits( theMedia );
AddVideoSamples( theMedia, &trackFrame, (long) max, spec->name );
err = EndMediaEdits( theMedia );
err = InsertMediaIntoTrack( theTrack, 0, 0, GetMediaDuration( theMedia ), 0x00010000L );
}
/* --------------------------------------------------------------------------------- */
static void AddVideoSamples( Media theMedia, Rect * trackFrame, long max,
unsigned char * picsFileName )
{
long maxCompressedSize;
GWorldPtr theGWorld;
long curSample;
Handle compressedData = nil;
Ptr compressedDataPtr;
ImageDescriptionHandle imageDesc = nil;
CGrafPtr oldPort;
GDHandle oldGDeviceH;
OSErr err = noErr;
short j;
err = NewGWorld( &theGWorld, 8 /* depth */, trackFrame, nil, nil, (GWorldFlags) 0 );
LockPixels( theGWorld->portPixMap );
err = GetMaxCompressionSize( theGWorld->portPixMap, trackFrame, 0,
codecNormalQuality, 'rle ', (CompressorComponent) anyCodec,
&maxCompressedSize );
compressedData = NewHandle( maxCompressedSize );
if (MemError())
{
errorHandlerParameter( ERR_MEMORY, picsFileName );
return;
}
MoveHHi( compressedData );
HLock( compressedData );
compressedDataPtr = StripAddress( *compressedData );
imageDesc = (ImageDescriptionHandle) NewHandle( 4L );
if (MemError())
{
errorHandlerParameter( ERR_MEMORY, picsFileName );
return;
}
GetGWorld( &oldPort, &oldGDeviceH );
SetGWorld( theGWorld, nil );
for (curSample=0L, j=basePictIndex; curSample<max; curSample++, j++)
{
EraseRect( trackFrame );
DrawMyFrame( trackFrame, j );
err = CompressImage( theGWorld->portPixMap, trackFrame, codecNormalQuality,
'rle ', imageDesc, compressedDataPtr );
err = AddMediaSample( theMedia, compressedData, 0, (**imageDesc).dataSize,
1, (SampleDescriptionHandle) imageDesc, 1, 0, nil );
}
SetGWorld( oldPort, oldGDeviceH );
if (imageDesc != NULL)
DisposeHandle( (Handle) imageDesc );
if (compressedData != NULL)
DisposeHandle( compressedData );
if (theGWorld != NULL)
DisposeGWorld( theGWorld );
}
/* --------------------------------------------------------------------------------- */
static void DrawMyFrame( Rect * trackFrame, short id )
{
Handle pict;
pict = Get1Resource( 'PICT', id );
if (pict == nil)
return;
LoadResource( pict );
DrawPicture( (PicHandle) pict, trackFrame );
ReleaseResource( pict );
}
/* --------------------------------------------------------------------------------- */
static Boolean inputFileValid( FSSpec * picsFile, Boolean interactive )
/*
Checks to see that the file if of type 'PICS'. Also, checks loads the PICS info
resource. If not found, dialog displayed if interactive, else, preferences
value is used.
*/
{
FInfo info;
Handle picsInfo;
short saveref, resfile;
Boolean infoValid = false;
if (FSpGetFInfo( picsFile, &info) != noErr)
{
errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
return false;
}
if (info.fdType != 'PICS')
{
errorHandlerParameter( ERR_NOT_PICS, picsFile->name );
return false;
}
saveref = CurResFile();
resfile = FSpOpenResFile( picsFile, fsRdPerm );
if (resfile == -1)
{
errorHandlerParameter( ERR_INPUT_FILE, picsFile->name );
return false;
}
picsInfo = Get1Resource( 'INFO', 128 );
if (picsInfo != nil)
{
if (SizeResource( picsInfo ) == sizeof( pics_info ))
{
LoadResource( picsInfo );
HLock( picsInfo );
BlockMove( *picsInfo, &rPICSInfo, sizeof( rPICSInfo ) );
HUnlock( picsInfo );
ReleaseResource( picsInfo );
if ((rPICSInfo.speed >= 1) && (rPICSInfo.speed <= 60))
infoValid = true;
}
}
UseResFile(saveref);
CloseResFile( resfile );
if (!infoValid)
{
if (!interactive)
rPICSInfo.speed = copyPrefsFPS();
else if (!preferencesDialog( &rPICSInfo.speed ))
return false; /* user canceled, so abort */
}
return true;
}
/* --------------------------------------------------------------------------------- */
static void buildName( unsigned char * newBaseName, unsigned char * variant )
{
static Str63 base = "\p"; /* stores file name last used */
static long nextNum = 1L; /* stores integer number for appending non-unique name */
static short insertPoint = 1; /* stores location to start inserting number */
unsigned char numText[12]; /* provide enough storage for largest possible long converted to string */
short len;
if (newBaseName != nil)
{
/* make a copy of the new base name */
pstrcpy( base, newBaseName );
len = (short) base[0];
/* if name ends in ".PICS", insert new extension at the '.' */
insertPoint = (!memcmpi( base+len-4, ".PICS", 5L )) ? (len-4) : (len+1);
/* max file name is 31 chars, need 3 chars for ".QT" extension */
if (insertPoint > 29)
insertPoint = 29;
base[insertPoint] = '.';
base[++insertPoint] = 'Q';
base[++insertPoint] = 'T';
base[0] = insertPoint++; /* set length of P string, inc insert point so intserting after the 'T' */
nextNum = 1L;
}
else
{
NumToString( nextNum++, numText );
if ((insertPoint + numText[0]) > 32) /* 32 is proper number, even though max len is 31 */
{
insertPoint -= ((insertPoint + numText[0]) - 32);
base[insertPoint-3] = '.';
base[insertPoint-2] = 'Q';
base[insertPoint-1] = 'T';
}
BlockMove( numText+1, base+insertPoint, (long) numText[0] );
base[0] = insertPoint + numText[0] - 1;
}
/* copy new file name to output buffer */
pstrcpy( variant, base );
}